Modelo Datos No Estructurados¶

Reconocimiento de imagenes¶

Con el uso de redes neuronales se logró crear una herramienta de reconocimiento de imágenes que permite a los usuarios recibir sugerencias según sus preferencias. Primeramente se creó una base de datos que contiene las siguientes variables:

  • HouseID: Id de la casa
  • Type: Si es casa que se vende o se renta o si ya se vendio(por temas de probar el modelo)
  • Sub_Type: Cada subtipo representa un estilo o configuración específica de una casa.
  • Style: Los 4 estilos mas vendidos de las casas (Contemporary/modern, Ranch, Traditional, Mediterranean).
  • Price: Precio de la casa
  • House Title: Direccion de la casa
  • ImageURL: Imagen URL encontrada en internet.

Para este modelo, se dividieron las categorías según los 4 estilos más vendidos de las casas. Además, se realizó una búsqueda extensa de fotografías y se crearon 4 carpetas que contienen entre 20 y 25 fotografías para cada estilo de casa

In [1]:
# Librerías importantes

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense
from keras import applications
from sklearn.metrics import pairwise_distances
import requests
from PIL import Image
import pickle
from datetime import datetime
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
import plotly.figure_factory as ff
import plotly.graph_objects as go
import plotly.express as px
import streamlit as st
#use the below library while displaying the images in jupyter notebook
from IPython.display import display, Image
import streamlit as st

houses_df = pd.read_excel("C:\\Users\\alexa\\OneDrive\\CONCENTRACION_LIT\\RETOFASE2\\houses.xlsx") # Set de datos con los id y categorias de los objetos
houses_df
Out[1]:
HouseId Type Sub_Type Style Price HouseTitle Image ImageURL
0 6740504 Buy Single-Family Contemporary/Modern 2500000 114 S Timber Top Dr 6740504.jpg https://rew-feed-images.global.ssl.fastly.net/...
1 14498187 Buy Townhouse Condominium Contemporary/Modern 269000 18 S Villa Oaks Dr 14498187.jpg https://rew-feed-images.global.ssl.fastly.net/...
2 18045693 Buy Single-Family Contemporary/Modern 550000 3 N Timber Top Dr 18045693.jpg https://rew-feed-images.global.ssl.fastly.net/...
3 22311505 Buy Single-Family Contemporary/Modern 2290000 139 Vue Point Pl 22311505.jpg https://rew-feed-images.global.ssl.fastly.net/...
4 27593002 Rental Single Family Detached Contemporary/Modern 2750 2 Eagle Rock Pl 27593002.jpg https://rew-feed-images.global.ssl.fastly.net/...
... ... ... ... ... ... ... ... ...
86 95801532 Sold Single-Family Mediterranean 1275000 51 Ironton Place 95801532.jpg https://ap.rdcpix.com/ac91e802cffb72613f6fa09c...
87 28451041 Sold Single-Family Mediterranean 763229 11 Papado Trails Circle 28451041.jpg https://ap.rdcpix.com/1949bc7460173a1912098136...
88 57585680 Sold Single-Family Mediterranean 598000 29 Cokeberry Street 57585680.jpg https://ssl.cdn-redfin.com/photo/104/mbpaddedw...
89 37286582 Sold Single-Family Mediterranean 967725 17 Honey Daffodil Place 37286582.jpg https://photos.zillowstatic.com/fp/54d11015cbf...
90 45040581 Sold Single-Family Mediterranean 1050000 23 Olmstead Row 45040581.jpg https://photos.harstatic.com/191763015/hr/img-...

91 rows × 8 columns

Observando caracteristicas y renombrando estilos¶

In [2]:
houses_df["Style"].value_counts()
print("Numero total de casas: ", houses_df.shape[0])
print("Numero de estilos de casas: ", houses_df["Style"].nunique())
Numero total de casas:  91
Numero de estilos de casas:  4

Definiendo el numero de estilos¶

In [3]:
# Se tienen 4 estilos
houses_contemporary = houses_df[houses_df["Style"]=="Contemporary/Modern"]
houses_ranch = houses_df[houses_df["Style"]=="Ranch"]
houses_traditional = houses_df[houses_df["Style"]=="Traditional"]
houses_mediterranean = houses_df[houses_df["Style"]=="Mediterranean"]
In [6]:
# Directorios (Cambiar por el propio cuando se descarguen las bases)
path = "C:\\Users\\alexa\\OneDrive\\CONCENTRACION_LIT\\RETOFASE2" # Directorio general donde se depositaran las caracteristicas e indices de las imagenes
try:
   os.chdir(path)
   print("Directorio actual: {0}".format(os.getcwd()))
except FileNotFoundError:
   print("Directorio: {0} no existe".format(path))
except NotADirectoryError:
   print("{0} no es un directorio".format(path))
except PermissionError:
   print("Sin permiso de modificar {0}".format(path))
Directorio actual: C:\Users\alexa\OneDrive\CONCENTRACION_LIT\RETOFASE2

Estilo Modern/Contemporary¶

Primeramente se define el directorio en donde se encuentran las imagenes de cada estilo.

In [8]:
img_width, img_height = 224, 224 # Pixeles de imagenes
train_data_dir = "C:\\Users\\alexa\\OneDrive\\CONCENTRACION_LIT\\RETOFASE2\\HOUSES_IMAGES\\CONT" # Directorio de imagenes de contemporary houses
In [9]:
train_data_dir 
Out[9]:
'C:\\Users\\alexa\\OneDrive\\CONCENTRACION_LIT\\RETOFASE2\\HOUSES_IMAGES\\CONT'
  • Utilizando el modelo ResNet50 primeramente definimos el número de muestras a utilizar(cantidad de fotos con las que se cuentan de cada categoria), el número de veces que se entrenará el modelo y el tamaño de los lotes de imágenes que se procesarán. En este caso se decidio utilizar una iteración de 100 para mejorar el rendimiento del modelo.

  • Despues de obtener las caracteristicas de este estilo de casa se almacenan en un archivo npy el cual previamente se utilizara en la plataforma de Visual Studio Code para su deployment en una apicacion local con el uso de la librería streamlit con el fin de probar el funcionamiento del mismo.

In [10]:
nb_train_samples = 20  # Muestras
epochs = 100  # Epocas (Episodios)
batch_size = 1  # Tamaño del lote

# Nota: Variar los parámetros de la parte superior (muestras, episodios y tamaño del lote) para modificar el rendimiento de la red

def extract_features():
    Itemcodes = []
    datagen = ImageDataGenerator(rescale=1. / 255)  # Escalamiento de las imagenes
    model = applications.ResNet50(include_top=False, weights='imagenet')  # Uso de ResNet50
    generator = datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode=None,
        shuffle=False
    )
    for i in generator.filenames:
        Itemcodes.append(i[(i.find("/") + 1):i.find(".")])
    extracted_features = model.predict(generator, nb_train_samples // batch_size)  # Extracción de características

    num_samples = extracted_features.shape[0]  # Get the actual number of samples
    num_features = extracted_features.size // num_samples  # Calculate the number of features per sample
    extracted_features = extracted_features.reshape((num_samples, -1))  # Reshape into (num_samples, num_features)

    np.save(open('./CONTEMPORARY_ResNet_features.npy', 'wb'), extracted_features)

a = datetime.now()
extract_features()
print("Tiempo de extraccion de caracteristicas", datetime.now() - a)
Found 20 images belonging to 1 classes.
20/20 [==============================] - 3s 96ms/step
Tiempo de extraccion de caracteristicas 0:00:05.718148
In [11]:
extracted_features = np.load('CONTEMPORARY_ResNet_features.npy')
contemporary =houses_contemporary.copy()
#contemporary = pd.read_csv('./houses_contemporary.csv')
df_Productids = list(contemporary['HouseId']) # Id de los productos

El siguiente código es una pruba de lo que se quiere lograr en el deployment de streamlit, aqui se puede observar como el modelo utiliza CNN para calcular la distancia eucladiana entre imagenes basada en sus características extraídas

In [12]:
def get_similar_products_cnn(product_id, num_results):
    doc_id = df_Productids.index(product_id)
    pairwise_dist = pairwise_distances(extracted_features, extracted_features[doc_id].reshape(1,-1))
    indices = np.argsort(pairwise_dist.flatten())[0:num_results]
    pdists  = np.sort(pairwise_dist.flatten())[0:num_results]
    print("="*20, "House Image", "="*20)
    ip_row = contemporary[['ImageURL','HouseTitle']].loc[contemporary['HouseId']==int(df_Productids[indices[0]])]
    #print(ip_row.head())
    for indx, row in ip_row.iterrows():
        display(Image(url=row['ImageURL'], width = 224, height = 224,embed=True))
        print('House Title: ', row['HouseTitle'])
    print("\n","="*20, "Recommended Houses", "="*20)
    for i in range(1,len(indices)):
        rows = contemporary[['ImageURL','HouseTitle']].loc[contemporary['HouseId']==int(df_Productids[indices[i]])]
        for indx, row in rows.iterrows():
            display(Image(url=row['ImageURL'], width = 224, height = 224,embed=True))
            print('House Title: ', row['HouseTitle'])
            print('Distancia euclidiana desde la imagen muestra:', pdists[i])
In [ ]:
En este caso como ejemplo tomamos la casa 50633300 del tipo contemporaneo y pedimos que muestre las 5 casas mas parecidas a 
la misma.
In [13]:
get_similar_products_cnn(50633300, 5)
==================== House Image ====================
House Title:  5 Crinkleroot Ct

 ==================== Recommended Houses ====================
House Title:  139 Vue Point Pl
Distancia euclidiana desde la imagen muestra: 35.923786
House Title:  39 Thornblade Cir
Distancia euclidiana desde la imagen muestra: 35.985115
House Title:   19 E Sunny Slope Cir
Distancia euclidiana desde la imagen muestra: 38.81897
House Title:   79 Huntsmans Horn Cir
Distancia euclidiana desde la imagen muestra: 38.902916

Categorías restantes¶

  • Este mismo proceso sucede con las 3 categorias restantes que son Ranch , Traditional y Mediterranean. Como se muestra a continuación:

RANCH¶

In [15]:
img_width, img_height = 224, 224


#top_model_weights_path = 'resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5'
train_data_dir = "C:\\Users\\alexa\\OneDrive\\CONCENTRACION_LIT\\RETOFASE2\\HOUSES_IMAGES\\RAN" # Directorio de imagenes de mujeres

# Nota: Se aplica el mismo procedimiento que el usado en las imagenes de ropa de hombre

nb_train_samples = 25 # Muestras CAMBIAR
epochs = 100  # Epocas (Episodios)
batch_size = 1  # Tamaño del lote

# Nota: Variar los parámetros de la parte superior (muestras, episodios y tamaño del lote) para modificar el rendimiento de la red

def extract_features():
    Itemcodes = []
    datagen = ImageDataGenerator(rescale=1. / 255)  # Escalamiento de las imagenes
    model = applications.ResNet50(include_top=False, weights='imagenet')  # Uso de ResNet50
    generator = datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode=None,
        shuffle=False
    )
    for i in generator.filenames:
        Itemcodes.append(i[(i.find("/") + 1):i.find(".")])
    extracted_features = model.predict(generator, nb_train_samples // batch_size)  # Extracción de características

    num_samples = extracted_features.shape[0]  # Get the actual number of samples
    num_features = extracted_features.size // num_samples  # Calculate the number of features per sample
    extracted_features = extracted_features.reshape((num_samples, -1))  # Reshape into (num_samples, num_features)

    np.save(open('./RANCH_ResNet_features.npy', 'wb'), extracted_features)

a = datetime.now()
extract_features()
print("Tiempo de extraccion de caracteristicas", datetime.now() - a)
Found 25 images belonging to 1 classes.
25/25 [==============================] - 3s 91ms/step
Tiempo de extraccion de caracteristicas 0:00:05.163063
In [16]:
extracted_features = np.load('RANCH_ResNet_features.npy')
ranch =houses_ranch.copy()
#contemporary = pd.read_csv('./houses_contemporary.csv')
df_Productids = list(ranch['HouseId']) # Id de los productos
In [17]:
def get_similar_products_cnn(product_id, num_results):
    doc_id = df_Productids.index(product_id)
    pairwise_dist = pairwise_distances(extracted_features, extracted_features[doc_id].reshape(1,-1))
    indices = np.argsort(pairwise_dist.flatten())[0:num_results]
    pdists  = np.sort(pairwise_dist.flatten())[0:num_results]
    print("="*20, "House Image", "="*20)
    ip_row = ranch[['ImageURL','HouseTitle']].loc[ranch['HouseId']==int(df_Productids[indices[0]])]
    #print(ip_row.head())
    for indx, row in ip_row.iterrows():
        display(Image(url=row['ImageURL'], width = 224, height = 224,embed=True))
        print('House Title: ', row['HouseTitle'])
    print("\n","="*20, "Recommended Houses", "="*20)
    for i in range(1,len(indices)):
        rows = ranch[['ImageURL','HouseTitle']].loc[ranch['HouseId']==int(df_Productids[indices[i]])]
        for indx, row in rows.iterrows():
            display(Image(url=row['ImageURL'], width = 224, height = 224,embed=True))
            print('House Title: ', row['HouseTitle'])
            print('Distancia euclidiana desde la imagen muestra:', pdists[i])
In [18]:
get_similar_products_cnn(10901549, 5)
==================== House Image ====================
House Title:  14 Camber Pine Pl

 ==================== Recommended Houses ====================
House Title:  2 Tangle Brush Dr
Distancia euclidiana desde la imagen muestra: 23.89868
House Title:  37 Lance Leaf Road
Distancia euclidiana desde la imagen muestra: 25.358463
House Title:  21 E Brookberry Ct
Distancia euclidiana desde la imagen muestra: 25.419004
House Title:  5 Terravale Court
Distancia euclidiana desde la imagen muestra: 25.526335

TRADITIONAL¶

In [20]:
img_width, img_height = 224, 224


#top_model_weights_path = 'resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5'
train_data_dir = "C:\\Users\\alexa\\OneDrive\\CONCENTRACION_LIT\\RETOFASE2\\HOUSES_IMAGES\\TRADI" # Directorio de imagenes de mujeres

# Nota: Se aplica el mismo procedimiento que el usado en las imagenes de ropa de hombre

nb_train_samples = 20 # Muestras CAMBIAR
epochs = 100  # Epocas (Episodios)
batch_size = 1  # Tamaño del lote

# Nota: Variar los parámetros de la parte superior (muestras, episodios y tamaño del lote) para modificar el rendimiento de la red

def extract_features():
    Itemcodes = []
    datagen = ImageDataGenerator(rescale=1. / 255)  # Escalamiento de las imagenes
    model = applications.ResNet50(include_top=False, weights='imagenet')  # Uso de ResNet50
    generator = datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode=None,
        shuffle=False
    )
    for i in generator.filenames:
        Itemcodes.append(i[(i.find("/") + 1):i.find(".")])
    extracted_features = model.predict(generator, nb_train_samples // batch_size)  # Extracción de características

    num_samples = extracted_features.shape[0]  # Get the actual number of samples
    num_features = extracted_features.size // num_samples  # Calculate the number of features per sample
    extracted_features = extracted_features.reshape((num_samples, -1))  # Reshape into (num_samples, num_features)

    np.save(open('./TRADITIONAL_ResNet_features.npy', 'wb'), extracted_features)

a = datetime.now()
extract_features()
print("Tiempo de extraccion de caracteristicas", datetime.now() - a)
Found 20 images belonging to 1 classes.
20/20 [==============================] - 3s 109ms/step
Tiempo de extraccion de caracteristicas 0:00:05.636039
In [21]:
extracted_features = np.load('TRADITIONAL_ResNet_features.npy')
tradi =houses_traditional.copy()
#contemporary = pd.read_csv('./houses_contemporary.csv')
df_Productids = list(tradi['HouseId']) # Id de los productos
In [22]:
def get_similar_products_cnn(product_id, num_results):
    doc_id = df_Productids.index(product_id)
    pairwise_dist = pairwise_distances(extracted_features, extracted_features[doc_id].reshape(1,-1))
    indices = np.argsort(pairwise_dist.flatten())[0:num_results]
    pdists  = np.sort(pairwise_dist.flatten())[0:num_results]
    print("="*20, "House Image", "="*20)
    ip_row = tradi[['ImageURL','HouseTitle']].loc[tradi['HouseId']==int(df_Productids[indices[0]])]
    #print(ip_row.head())
    for indx, row in ip_row.iterrows():
        display(Image(url=row['ImageURL'], width = 224, height = 224,embed=True))
        print('House Title: ', row['HouseTitle'])
    print("\n","="*20, "Recommended Houses", "="*20)
    for i in range(1,len(indices)):
        rows = tradi[['ImageURL','HouseTitle']].loc[tradi['HouseId']==int(df_Productids[indices[i]])]
        for indx, row in rows.iterrows():
            display(Image(url=row['ImageURL'], width = 224, height = 224,embed=True))
            print('House Title: ', row['HouseTitle'])
            print('Distancia euclidiana desde la imagen muestra:', pdists[i])
In [23]:
get_similar_products_cnn(9149926, 5)
==================== House Image ====================
House Title:  91 E Bracebridge Cir

 ==================== Recommended Houses ====================
House Title:  11 Tiburon Ct
Distancia euclidiana desde la imagen muestra: 46.40416
House Title:  238 Flaxen Chestnut
Distancia euclidiana desde la imagen muestra: 49.336792
House Title:  110 E Grey Wing Court Ct
Distancia euclidiana desde la imagen muestra: 49.496166
House Title:  1 Southgate Dr
Distancia euclidiana desde la imagen muestra: 49.735847

MEDITERRANEAN¶

In [25]:
img_width, img_height = 224, 224


#top_model_weights_path = 'resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5'
train_data_dir = "C:\\Users\\alexa\\OneDrive\\CONCENTRACION_LIT\\RETOFASE2\\HOUSES_IMAGES\\MEDI" # Directorio de imagenes de mujeres

# Nota: Se aplica el mismo procedimiento que el usado en las imagenes de ropa de hombre

nb_train_samples = 26  # Muestras CAMBIAR
epochs = 100  # Epocas (Episodios)
batch_size = 1  # Tamaño del lote

# Nota: Variar los parámetros de la parte superior (muestras, episodios y tamaño del lote) para modificar el rendimiento de la red

def extract_features():
    Itemcodes = []
    datagen = ImageDataGenerator(rescale=1. / 255)  # Escalamiento de las imagenes
    model = applications.ResNet50(include_top=False, weights='imagenet')  # Uso de ResNet50
    generator = datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode=None,
        shuffle=False
    )
    for i in generator.filenames:
        Itemcodes.append(i[(i.find("/") + 1):i.find(".")])
    extracted_features = model.predict(generator, nb_train_samples // batch_size)  # Extracción de características

    num_samples = extracted_features.shape[0]  # Get the actual number of samples
    num_features = extracted_features.size // num_samples  # Calculate the number of features per sample
    extracted_features = extracted_features.reshape((num_samples, -1))  # Reshape into (num_samples, num_features)

    np.save(open('./MEDITERRANEAN_ResNet_features.npy', 'wb'), extracted_features)

a = datetime.now()
extract_features()
print("Tiempo de extraccion de caracteristicas", datetime.now() - a)
Found 26 images belonging to 1 classes.
26/26 [==============================] - 4s 107ms/step
Tiempo de extraccion de caracteristicas 0:00:06.699287
In [26]:
extracted_features = np.load('MEDITERRANEAN_ResNet_features.npy')
medi =houses_mediterranean.copy()
#contemporary = pd.read_csv('./houses_contemporary.csv')
df_Productids = list(medi['HouseId']) # Id de los productos
In [27]:
def get_similar_products_cnn(product_id, num_results):
    doc_id = df_Productids.index(product_id)
    pairwise_dist = pairwise_distances(extracted_features, extracted_features[doc_id].reshape(1,-1))
    indices = np.argsort(pairwise_dist.flatten())[0:num_results]
    pdists  = np.sort(pairwise_dist.flatten())[0:num_results]
    print("="*20, "House Image", "="*20)
    ip_row = medi[['ImageURL','HouseTitle']].loc[medi['HouseId']==int(df_Productids[indices[0]])]
    #print(ip_row.head())
    for indx, row in ip_row.iterrows():
        display(Image(url=row['ImageURL'], width = 224, height = 224,embed=True))
        print('House Title: ', row['HouseTitle'])
    print("\n","="*20, "Recommended Houses", "="*20)
    for i in range(1,len(indices)):
        rows = medi[['ImageURL','HouseTitle']].loc[medi['HouseId']==int(df_Productids[indices[i]])]
        for indx, row in rows.iterrows():
            display(Image(url=row['ImageURL'], width = 224, height = 224,embed=True))
            print('House Title: ', row['HouseTitle'])
            print('Distancia euclidiana desde la imagen muestra:', pdists[i])
In [28]:
get_similar_products_cnn(3108527, 5)
==================== House Image ====================
House Title:  83 Lakeside Grn

 ==================== Recommended Houses ====================
House Title:  51 Ironton Place
Distancia euclidiana desde la imagen muestra: 27.289204
House Title:  11 Papado Trails Circle
Distancia euclidiana desde la imagen muestra: 28.980757
House Title:  6 Paloma Bend Place
Distancia euclidiana desde la imagen muestra: 29.419434
House Title:  35 Winter Thicket Place
Distancia euclidiana desde la imagen muestra: 29.889215

Visual Studio Code¶

Después de extraer con éxito las caracteristicas de las casas se utilizo la plataforma de Visual Studio Code junto con la librería de Streamlit para construir la aplicación local de recomendación para Tamborrel. La aplicación funciona de igual manera que en los ejemplos anteriores.

ESTE CÓDIGO SOLO FUNCIONA EN LA PLATAFORMA DE VISUAL STUDIO CODE

In [ ]:
import numpy as np
import pandas as pd
from PIL import Image
from PIL import ImageFile
import urllib.request
#from IPython.display import display, Image
from sklearn.metrics import pairwise_distances
from datetime import datetime
import streamlit as st

# Directorios (Cambiar por el propio cuando se descarguen las bases)
path = "C:/Users/alexa/OneDrive/CONCENTRACION_LIT/RETOFASE2"

 # Directorio general donde se depositaran las caracteristicas e indices de las imagenes
try:
   os.chdir(path)
   print("Directorio actual: {0}".format(os.getcwd()))
except FileNotFoundError:
   print("Directorio: {0} no existe".format(path))
except NotADirectoryError:
   print("{0} no es un directorio".format(path))
except PermissionError:
   print("Sin permiso de modificar {0}".format(path))

# In[4]:

st.set_option('deprecation.showfileUploaderEncoding', False)

# Uso de las características extraídas por categoría

houses_df = pd.read_excel("C:/Users/alexa/OneDrive/CONCENTRACION_LIT/RETOFASE2/houses.xlsx")
contemporary_features = np.load('C:/Users/alexa/OneDrive/CONCENTRACION_LIT/RETOFASE2/CONTEMPORARY_ResNet_features.npy')
mediterranean_features = np.load('C:/Users/alexa/OneDrive/CONCENTRACION_LIT/RETOFASE2/MEDITERRANEAN_ResNet_features.npy')
traditional_features = np.load('C:/Users/alexa/OneDrive/CONCENTRACION_LIT/RETOFASE2/TRADITIONAL_ResNet_features.npy')
ranch_features = np.load('C:/Users/alexa/OneDrive/CONCENTRACION_LIT/RETOFASE2/RANCH_ResNet_features.npy')
houses_df["HouseId"] = houses_df["HouseId"].astype(str)

# Indices de los objetos por categoría


houses_contemporary = houses_df[houses_df["Style"]=="Contemporary/Modern"]
houses_ranch = houses_df[houses_df["Style"]=="Ranch"]
houses_traditional = houses_df[houses_df["Style"]=="Traditional"]
houses_mediterranean = houses_df[houses_df["Style"]=="Mediterranean"]

def get_similar_products_cnn(product_id, num_results): # Primero definir la categoria
    if(houses_df[houses_df['HouseId']==product_id]['Style'].values[0]=="Contemporary/Modern"):
        extracted_features = contemporary_features
        Productids = list(houses_contemporary['HouseId'])
    elif(houses_df[houses_df['HouseId']==product_id]['Style'].values[0]=="Ranch"):
        extracted_features = ranch_features
        Productids = list(houses_ranch['HouseId'])
    elif(houses_df[houses_df['HouseId']==product_id]['Style'].values[0]=="Mediterranean"):
        extracted_features = mediterranean_features
        Productids = list(houses_mediterranean['HouseId'])
    elif(houses_df[houses_df['HouseId']==product_id]['Style'].values[0]=="Traditional"):
        extracted_features = traditional_features
        Productids = list(houses_traditional['HouseId'])
    Productids = list(Productids)
    doc_id = Productids.index(product_id) # Id de los productos
    pairwise_dist = pairwise_distances(extracted_features, extracted_features[doc_id].reshape(1,-1))
    indices = np.argsort(pairwise_dist.flatten())[0:num_results]
    pdists  = np.sort(pairwise_dist.flatten())[0:num_results]
    st.write("""
         #### Details 
         """)
    ip_row = houses_df[['ImageURL','HouseTitle']].loc[houses_df['HouseId']==Productids[indices[0]]]
    for indx, row in ip_row.iterrows():
        image = Image.open(urllib.request.urlopen(row['ImageURL']))
        image = image.resize((224,224))
        st.image(image)
        st.write(f"Chosen House : {row['HouseTitle']}")
    st.write(f"""
         #### The {num_results} houses recommended for you are: 
         """)
    for i in range(1,len(indices)):
        rows = houses_df[['ImageURL','HouseTitle']].loc[houses_df['HouseId']==Productids[indices[i]]]
        for indx, row in rows.iterrows():
            #image = Image.open(Image(url=row['ImageURL'], width = 224, height = 224,embed=True))
            image = Image.open(urllib.request.urlopen(row['ImageURL']))
            image = image.resize((224,224))
            st.image(image)
            st.write(f"House Title: {row['HouseTitle']}")
            st.write(f"Distance of the image: {pdists[i]}")

st.write("""
         ## House Recommendation
         """
         )


user_input1 = st.text_input("Insert the Id of the house you liked the most")
user_input2 = st.text_input("Insert the number of recommendations you would like to see")


button = st.button('Generate recommendations')
if button:
    get_similar_products_cnn(str(user_input1), int(user_input2))

Ejecución¶

Para ejecutar la aplicación se bre una nueva terminal en Visual Code y se utiliza el nombre del archivo y el conjunto de streamlit, en nuestro caso ejemplo es:

streamlit run SistemaRecomendacion_Despliegue4.py

Actualmente, nuestro modelo de reconocimiento de imágenes funciona gracias a un catálogo en el cual el usuario elige el estilo de casa de su preferencia para obtener recomendaciones. Nuestro objetivo es expandir este modelo y aumentar la base de datos de las fotografías de casas y a su vez realizar el deployment del modelo integrandolo en nuestro Chatbot como una opción interactiva para los compradores/clientes de Tamborrel.

Para finalizar nos gustaría escalar el modelo al permitir que los usuarios suban una imagen de su casa ideal y asi utilizar el sistema de reconocimiento de imágenes para encontrar propiedades similares en los listings de las casas de la pagina de Tamborrel. Esto nos ayudará a mejorar la experiencia del usuario al brindarle la opción de búsqueda basada en imágenes.

Visualización¶

In [1]:
from IPython.display import Image
Image(filename='C:/Users/alexa/OneDrive/CONCENTRACION_LIT/RETOFASE2/recon.jpeg')
Out[1]: